<template>
  <div>
    <VxeTableVue
      ref="tableEl"
      module-name="用户"
      :queryFormData="state.formData"
      :column-config="columnConfig"
      data-list-api="/auth/user/page"
      delete-api="/auth/user"
      add-permi="user-add-user"
      del-permi="user-del-user"
      update-permi="user-uodate-user"
      :show-action-column="hasPermi(['user-uodate-user', 'user-del-user'])"
      :add-data="state.addItemData"
      :dialog-form-rules="mapRules"
      @before-open-dialog="onBeforeOpenDialog"
      @before-submit="onBeforeSubmit"
      @refactor-dialog-params="onRefactorDalogParms"
    >
      <!------------------------------------------ 查询 ------------------------------------------------------->

      <template #queryItem>
        <el-form-item label="用户" prop="keyword" class="mgr30">
          <el-input v-model="state.formData.keyword" placeholder="账号、姓名或拼音首字母" clearable />
        </el-form-item>
        <el-form-item label="用户状态" prop="lockFlag" class="mgr30">
          <SelectVue
            v-model="state.formData.lockFlag"
            :option-list="[
              { name: '启用', id: '0' },
              { name: '禁用', id: '1' }
            ]"
            style="width: 200px"
            clearable
          />
        </el-form-item>
        <el-form-item label="角色" prop="roleIds" class="mgr30">
          <SelectVue v-model="state.formData.roleIds" label="roleName" :option-list="state.roleList" clearable style="width: 200px" />
        </el-form-item>
      </template>

      <!------------------------------------------ 表格列 ------------------------------------------------------->

      <template #lockFlag="{ row }: SlotUser">
        <el-tag :type="row.lockFlag === '0' ? 'success' : 'danger'">{{ row.lockFlag === '0' ? '启用' : '禁用' }}</el-tag>
      </template>
      <template #roleList="{ row }: SlotUser">
        <div>
          {{
            row.roleList
              ?.filter(item => item.lockFlag === '0')
              .map(item => item.roleName)
              .join(',')
          }}
        </div>
      </template>

      <template #topExtra="{ selectedList }">
        <span class="mgl20">已选</span>
        <span class="mgr5 mgl5" style="color: var(--el-color-primary)">{{ selectedList.length }}</span>
        <span>个</span>
      </template>

      <template #extraBtn2="{ row }: SlotUser">
        <el-button v-has-permi="['user']" type="primary" link @click="handleStatus(row)">{{ row.lockFlag === '1' ? '启用' : '禁用' }}</el-button>
      </template>

      <!------------------------------------------ 新增修改 ------------------------------------------------------->

      <template #dialogUpdateOrAdd="{ row }: SlotUser">
        <el-row class="flex">
          <el-form-item label="账号" prop="username" class="mgr30 flex1">
            <el-input v-model="row.username" placeholder="请输入数字和字母" clearable />
          </el-form-item>
          <el-form-item label="姓名" prop="name" class="flex1">
            <el-input v-model="row.name" placeholder="请输入姓名" clearable />
          </el-form-item>
        </el-row>
        <el-row class="flex">
          <el-form-item label="手机号" prop="phone" class="mgr30 flex1">
            <el-input v-model="row.phone" placeholder="请输入手机号" clearable />
          </el-form-item>
          <el-form-item label="角色" prop="roleIds" class="flex1">
            <SelectVue v-model="row.roleIds" :transfer="false" label="roleName" :option-list="state.roleList" multiple collapse-tags collapse-tags-tooltip clearable />
          </el-form-item>
        </el-row>
        <el-row class="flex">
          <el-form-item label="密码" prop="password" class="mgr30 flex1">
            <el-input v-model="row.password" placeholder="请输入密码" clearable />
          </el-form-item>
          <el-form-item label="确认密码" prop="confirmPassword" class="flex1">
            <el-input v-model="row.confirmPassword" placeholder="请确认密码" clearable />
          </el-form-item>
        </el-row>
      </template>
    </VxeTableVue>
  </div>
</template>

<script setup lang="ts">
  import { ref, reactive, computed } from 'vue'
  import { type VxeTableViewInstance, VxeTableVue } from '@/components/table'
  import { columnConfig } from './config'
  import { Ui, hasPermi } from '@/utils'
  import request, { type IPage } from '@/service'
  import { type ValidateFn } from '@/components/dialog'
  import SelectVue from '@/components/select'
  import type { IUserEntity, IRoleEntity } from '@/types'
  import { md5 } from 'js-md5'
  import { omit } from 'xe-utils'

  interface IUserFormData extends IUserEntity {
    password: string
    confirmPassword: string
    roleIds: string[]
  }

  type SlotUser = { row: IUserFormData }

  const tableEl = ref<VxeTableViewInstance | null>()

  const initAddData = () => {
    return {
      username: '',
      password: '',
      confirmPassword: '',
      lockFlag: '',
      phone: '',
      name: '',
      roleIds: []
    }
  }

  const state = reactive({
    formData: {
      keyword: '',
      lockFlag: '',
      roleIds: ''
    },
    dialogType: '' as 'add' | 'update',

    addItemData: initAddData(),

    roleList: [] as IRoleEntity[]
  })

  const rules = {
    username: [{ required: true, pattern: /^[A-Za-z0-9]+$/, message: '请输入数字和字母', trigger: 'change' }],
    name: [{ required: true, message: '请输入姓名', trigger: 'change' }],
    phone: [
      { required: true, pattern: /^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[1589]))\d{8}$/, message: '请输入正确格式手机号', trigger: 'change' }
    ],
    roleIds: [{ required: true, message: '请选择角色', trigger: 'change' }],
    password: [{ required: true, message: '请输入密码', trigger: 'change' }],
    confirmPassword: [{ required: true, message: '请再次输入密码', trigger: 'change' }]
  }

  const mapRules = computed(() => (state.dialogType === 'add' ? rules : omit(rules, ['password', 'confirmPassword'])))

  /**----------------------------methods----------------------------------------------------------------------- */

  /**
   * 提交前校验
   * @param data
   * @param fn/^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[1589]))\d{8}$/
   */
  const onBeforeSubmit = (data: IUserFormData, fn: ValidateFn) => {
    const diff = data.password === data.confirmPassword
    fn(diff, diff ? '' : '请输入相同密码')
  }

  const onRefactorDalogParms = (type: 'add' | 'update', data: IUserFormData, fn: ValidateFn) => {
    fn(false)

    const params = { ...data }
    const method = type === 'add' ? 'post' : 'put'

    if (params.password && params.confirmPassword) {
      params.password = md5(params.password)
      params.confirmPassword = md5(params.confirmPassword)
    }

    tableEl.value?.setDialogLoading(true)

    request[method]('/auth/user', params)
      .then(res => {
        if (res.code !== 0) return Ui.useMessage('error', res.msg)
        Ui.useMessage('success', res.msg)
        tableEl.value?.handleCloseDialog()
        tableEl.value?.query()
      })
      .finally(() => tableEl.value?.setDialogLoading(false))
  }

  const onBeforeOpenDialog = (type: 'add' | 'update', data: IUserFormData) => {
    state.dialogType = type
    if (type === 'update') {
      data.roleIds = data.roleList?.filter(item => item.lockFlag === '0').map(item => item.id) ?? []
    } else {
      state.addItemData = initAddData()
    }
  }

  /**
   * 启用 禁用
   * @param row
   */
  const handleStatus = (user: IUserEntity) => {
    const handleConfirm = () => {
      user.lockFlag = user.lockFlag === '0' ? '1' : '0'
      request.put('/auth/user', user).then(res => {
        if (res.code !== 0) return Ui.useMessage('error', res.msg)
        tableEl.value?.query()
      })
    }

    Ui.useMessageBox({
      handleConfirm,
      text: user.lockFlag === '1' ? '启用后可正常使用系统，确定启用?' : '禁用后将无法登录系统，确定禁用?'
    })
  }

  /**
   * 获取角色
   */
  const getRoleList = () => {
    const params = {
      current: 1,
      size: 9999,
      lockFlag: '0'
    }
    request.get<IPage<IRoleEntity>>('/auth/role/page', params).then(res => {
      if (res.code !== 0) return Ui.useMessage('error', res.msg)
      state.roleList = res.data.records
    })
  }

  /**----------------------------lifecycle----------------------------------------------------------------------- */
  getRoleList()
</script>

<style scoped></style>
